﻿using Share;
using System;
using System.Collections.Generic;

/// <summary>
/// 提供各种随机数生成工具方法
/// </summary>
public static class RandomTools
{
    private static readonly Random random = new Random();
    /// <summary>
    /// 生成指定范围内的随机数
    /// </summary>
    /// <typeparam name="T">数值类型（int或float）</typeparam>
    /// <param name="min">最小值（包含）</param>
    /// <param name="max">最大值（int包含，float不包含）</param>
    /// <returns>范围内的随机数</returns>
    public static T RandomRange<T>(T min, T max) where T : IComparable
    {
        if (typeof(T) == typeof(int))
        {
            int minValue = Convert.ToInt32(min);
            int maxValue = Convert.ToInt32(max);
            return (T)(object)random.Next(minValue, maxValue + 1);
        }
        else if (typeof(T) == typeof(double))
        {
            double minValue = Convert.ToDouble(min);
            double maxValue = Convert.ToDouble(max);
            return (T)(object)(minValue + random.NextDouble() * (maxValue - minValue));
        }
        else if (typeof(T) == typeof(float))
        {
            float minValue = Convert.ToSingle(min);
            float maxValue = Convert.ToSingle(max);
            return (T)(object)(minValue + (float)random.NextDouble() * (maxValue - minValue));
        }
        else
        {
            throw new NotSupportedException($"类型 {typeof(T)} 不支持随机数生成");
        }
    }

    /// <summary>
    /// 从列表中随机获取一个元素
    /// </summary>
    /// <typeparam name="T">元素类型</typeparam>
    /// <param name="itemList">源列表</param>
    /// <returns>随机元素</returns>
    /// <exception cref="ArgumentException">列表为空时抛出</exception>
    public static T GetRandList<T>(IList<T> itemList)
    {
        if (itemList == null || itemList.Count == 0)
        {
            throw new ArgumentException("The list must not be null or empty.");
        }
        if (itemList.Count == 1)
        {
            return itemList[0];
        }
        return itemList[RandomRange(0, itemList.Count - 1)];
    }
    /// <summary>
    /// 获取单位圆内的随机点并乘以指定距离
    /// </summary>
    /// <param name="distance">距离</param>
    /// <returns>随机点</returns>
    public static UnityEngine.Vector3 GetRandomInsideUnitCircle(float distance)
    {
        return UnityEngine.Random.insideUnitCircle * distance;
    }
    /// <summary>
    /// 根据权重列表获取随机项索引,每一项为万分之，总体加起来不能超过10000
    /// </summary>
    /// <param name="weights">权重列表</param>
    /// <returns>选中项的索引</returns>
    /// <exception cref="InvalidOperationException">列表为空时抛出</exception>
    public static int GetItemFromRateList2<T>(IList<T> weights) where T : IComparable
    {
        if (weights == null || weights.Count == 0)
        {
            throw new InvalidOperationException("权重列表不能为空");
        }

        if (weights.Count == 1)
        {
            return 0;
        }

        long totalWeight = 0;
        foreach (var weight in weights)
        {
            if (weight.CompareTo(default(T)) < 0)
            {
                throw new ArgumentException("权重值不能为负数");
            }
            totalWeight += Convert.ToInt64(weight);
        }

        if (totalWeight == 0)
        {
            return RandomRange(0, weights.Count - 1);
        }

        long randomNumber = RandomRange(0, 10000);
        long currentSum = 0;

        for (int i = 0; i < weights.Count; i++)
        {
            currentSum += Convert.ToInt64(weights[i]);
            if (randomNumber < currentSum)
            {
                return i;
            }
        }
        ///都不在，就是最后一个
        return -1;
    }

    /// <summary>
    /// 根据权重列表获取随机项索引
    /// </summary>
    /// <param name="weights">权重列表</param>
    /// <returns>选中项的索引</returns>
    /// <exception cref="InvalidOperationException">列表为空时抛出</exception>
    public static int GetItemFromRateList<T>(IList<T> weights) where T : IComparable
    {
        if (weights == null || weights.Count == 0)
        {
            throw new InvalidOperationException("权重列表不能为空");
        }

        if (weights.Count == 1)
        {
            return 0;
        }

        long totalWeight = 0;
        foreach (var weight in weights)
        {
            if (weight.CompareTo(default(T)) < 0)
            {
                throw new ArgumentException("权重值不能为负数");
            }
            totalWeight += Convert.ToInt64(weight);
        }

        if (totalWeight == 0)
        {
            return RandomRange(0, weights.Count - 1);
        }

        long randomNumber = RandomRange(0, (int)(totalWeight - 1));
        long currentSum = 0;

        for (int i = 0; i < weights.Count; i++)
        {
            currentSum += Convert.ToInt64(weights[i]);
            if (randomNumber < currentSum)
            {
                return i;
            }
        }

        throw new InvalidOperationException("权重计算异常");
    }

    /// <summary>
    /// 获取矩形区域内的随机点
    /// </summary>
    /// <param name="rect">矩形区域</param>
    /// <returns>随机点</returns>
    public static UnityEngine.Vector2 GetRandRectPoint(UnityEngine.Rect rect)
    {
        return new UnityEngine.Vector2(
            RandomRange(rect.xMin, rect.xMax),
            RandomRange(rect.yMin, rect.yMax)
        );
    }

    /// <summary>
    /// 获取随机布尔值
    /// </summary>
    /// <returns>随机true或false</returns>
    public static bool RandomBool()
    {
        return RandomRange(0, 1) == 1;
    }

    /// <summary>
    /// 获取随机颜色
    /// </summary>
    /// <param name="includeAlpha">是否包含透明度</param>
    /// <returns>随机颜色</returns>
    public static UnityEngine.Color RandomColor(bool includeAlpha = false)
    {
        return new UnityEngine.Color(
            RandomRange(0f, 1f),
            RandomRange(0f, 1f),
            RandomRange(0f, 1f),
            includeAlpha ? RandomRange(0f, 1f) : 1f
        );
    }

    /// <summary>
    /// 随机打乱列表顺序
    /// </summary>
    /// <typeparam name="T">元素类型</typeparam>
    /// <param name="list">要打乱的列表</param>
    public static void Shuffle<T>(IList<T> list)
    {
        int n = list.Count;
        while (n > 1)
        {
            n--;
            int k = RandomRange(0, n);
            (list[k], list[n]) = (list[n], list[k]);
        }
    }

    internal static int RandomIndex(int count)
    {
        if (count == 0)
        {
            XKLog.LogError("RandomIndex 获取 0 的随机序列");
            return -1;
        }
        if (count < 1)
            return 0;
        return RandomRange(0, count - 1);
    }
    internal static int RandomInt(int v, int max)
    {
        return RandomRange(v, max);
    }
    internal static float RandomFloat(float v, float max)
    {
        return RandomRange(v, max);
    }
}
